package com.atguigu.gmall.realtime.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.atguigu.gmall.realtime.common.GmallConfig;
import org.apache.commons.lang3.StringUtils;
import org.apache.hadoop.hbase.client.Connection;
import redis.clients.jedis.Jedis;

/**
 * @author Felix
 * @date 2023/7/17
 * 查询维度的工具类
 */
public class DimUtil {

    /**
     * 获取维度数据的方法
     * 优化：旁路缓存
     * 旁路缓存的思路：先从缓存中获取维度数据，如果在缓存中找到了要关联的维度，直接将其作为返回值进行返回(缓存命中)；
     *              如果在缓存中没有找到要关联的维度数据，那么发送请求到hbase表中进行查询，然后将查询的结果放到
     *              缓存中缓存起来，方便下次查询使用。
     * 缓存产品的选型：
     *      状态：     性能很好，维护性差
     *      Redis：   性能也不错，维护性好     √
     * Redis相关的设置：
     *      key：        维度表名:主键值    例如：   dim_base_trademark:1
     *      value类型:   string
     *      expire：     1day
     *      注意： 如果维度数据发生了变化，清除redis中缓存的数据
     * @param redisClient
     * @param conn
     * @param nameSpace
     * @param tableName
     * @param id
     * @return
     */
    public static JSONObject getDimInfo(Jedis redisClient,
                                        Connection conn,
                                        String nameSpace,
                                        String tableName,
                                        String id
    ){
        //拼接从Redis中获取维度数据的key
        String key =  tableName.toLowerCase() + ":" + id;

        //用于接收从Redis中查询的数据
        String dimInfoStr = null;
        //用于封装返回的维度对象
        JSONObject dimInfoJsonObj = null;

        try {
            // 先从缓存中获取维度数据
            dimInfoStr = redisClient.get(key);
            if(StringUtils.isNotEmpty(dimInfoStr)){
                // 如果在缓存中找到了要关联的维度，直接将其作为返回值进行返回(缓存命中)
                dimInfoJsonObj = JSON.parseObject(dimInfoStr);
            }else{
                // 如果在缓存中没有找到要关联的维度数据，那么发送请求到hbase表中进行查询
                //底层调用的HbaseUtil工具类中查询维度的方法
                System.out.println("发送请求到hbase中查询维度");
                dimInfoJsonObj = HbaseUtil.getDimInfoFromHbase(conn, nameSpace, tableName, id);
                if(dimInfoJsonObj != null){
                    //将查询的结果放到缓存中缓存起来，方便下次查询使用
                    redisClient.setex(key,24*3600,dimInfoJsonObj.toJSONString());
                }else{
                    System.out.println("没有找到对应的维度数据:"+tableName +"_" + id);
                }
            }

        } catch (Exception e) {
            System.out.println("查询维度数据发生了异常");
        }
        return dimInfoJsonObj;
    }

    //从Redis中清除掉缓存的数据
    public static void delCached(String tableName,String id){
        String key = tableName.toLowerCase() + ":" + id;
        Jedis jedis = null;
        try {
            jedis = RedisUtil.getRedisClient();
            jedis.del(key);
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("从Redis中清除缓存数据发生了异常");
        } finally {
            RedisUtil.closeRedisClient(jedis);
        }
    }
    public static void main(String[] args) {
        Jedis jedis = RedisUtil.getRedisClient();
        Connection conn = HbaseUtil.getConnection();
        System.out.println(getDimInfo(jedis, conn, GmallConfig.HBASE_NAMESPACE, "dim_base_trademark", "1"));
        RedisUtil.closeRedisClient(jedis);
        HbaseUtil.closeConnection(conn);
    }
}
